package mapper

import (
	"encoding/xml"
	"errors"
	"go-quick/interface/iorm"
	"strings"
)

type (
	Node struct {
		XMLName  xml.Name
		Content  string     `xml:",innerxml"`
		Attrs    []xml.Attr `xml:",any,attr"`
		Children []Node     `xml:",any"`
	}

	XmlNode interface {
		Key() string
	}

	Namespace struct {
		mapper map[string]XmlMapper
	}

	XmlMapper struct {
		Name      xml.Name       `xml:"mapper"`
		Namespace string         `xml:"namespace,attr"`
		Sqls      []XmlSql       `xml:"sql"`
		Selects   []XmlSelect    `xml:"select"`
		Updates   []XmlNotSelect `xml:"update"`
		Insert    []XmlNotSelect `xml:"insert"`
		Deletes   []XmlNotSelect `xml:"delete"`
	}

	XmlSql struct {
		ID string `xml:"id,attr"`
	}

	XmlInclude struct {
		RefID string `xml:"refid,attr"`
	}

	XmlSelect struct {
		ID            string `xml:"id,attr"`
		ParameterType string `xml:"parameterType,attr"`
		ResultType    string `xml:"resultType,attr"`
		Content       []byte `xml:",innerxml"`
	}

	XmlNotSelect struct {
		ID            string `xml:"id,attr"`
		ParameterType string `xml:"parameterType,attr"`
		Content       []byte `xml:",innerxml"`
	}
)

func (s XmlSelect) Key() string {
	return s.ID
}

func (s XmlNotSelect) Key() string {
	return s.ID
}

func New(content string) *XmlMapper {
	var mapper XmlMapper
	decoder := xml.NewDecoder(strings.NewReader(content))
	if err := decoder.Decode(&mapper); err != nil {
		return nil
	}
	return &mapper
}

func New2(content string) *Node {
	var node Node
	decoder := xml.NewDecoder(strings.NewReader(content))
	if err := decoder.Decode(&node); err != nil {
		return nil
	}
	return &node
}

func find[T XmlNode](key string, data []T) int {
	for index, item := range data {
		if item.Key() == key {
			return index
		}
	}
	return -1
}

// Parse 解析
func (m *XmlMapper) Parse(types iorm.SqlType, sqlId string, vars ...any) (sql string, params []any, err error) {
	findXml, err := m.findXml(types, sqlId)
	if err != nil {
		return "", nil, err
	}
	return m.parse(findXml, vars...)

}

func (m *XmlMapper) findXml(types iorm.SqlType, sqlId string) (any, error) {
	var (
		index int
	)
	switch types {
	case iorm.Select:
		if index = find[XmlSelect](sqlId, m.Selects); index != -1 {
			return m.Selects[index], nil
		}
	case iorm.Insert:
		if index = find[XmlNotSelect](sqlId, m.Insert); index != -1 {
			return m.Insert[index], nil
		}
	case iorm.Delete:
		if index = find[XmlNotSelect](sqlId, m.Deletes); index != -1 {
			return m.Deletes[index], nil
		}
	case iorm.Update:
		if index = find[XmlNotSelect](sqlId, m.Updates); index != -1 {
			return m.Updates[index], nil
		}
	}
	return nil, errors.New("not exist")
}

// parse 解析
func (m *XmlMapper) parse(xml any, vars ...any) (sql string, params []any, err error) {
	//var buf strings.Builder
	//switch ojb := xml.(type) {
	//case XmlSelect:
	//
	//case XmlNotSelect:
	//
	//}
	return "", nil, err
}
